//! Session Actor
//! 
//! This actor manages individual test session execution,
//! corresponding to HttpRunner's SessionRunner.

use crate::actors::messages::*;
use crate::actors::{PluginActor, AIOrchestrationActor, ReportActor};
use crate::error::Result;
use crate::models::{
    testcase::TestCase,
    step::StepContext,
    summary::TestCaseSummary,
    ValueMap,
};
use coerce::actor::{Actor, ActorRef};
use coerce::actor::context::ActorContext;
use coerce::actor::message::Handler;
use async_trait::async_trait;
use std::collections::HashMap;
use uuid::Uuid;

/// Session Actor (corresponds to HttpRunner's SessionRunner)
#[derive(Debug)]
pub struct SessionActor {
    /// Session ID
    session_id: Uuid,
    
    /// Session variables
    variables: ValueMap,
    
    /// Plugin actor reference
    plugin_actor: Option<ActorRef<PluginActor>>,
    
    /// AI orchestration actor reference
    ai_actor: Option<ActorRef<AIOrchestrationActor>>,
    
    /// Report actor reference
    report_actor: Option<ActorRef<ReportActor>>,
    
    /// Current test case
    current_test_case: Option<TestCase>,
    
    /// Session summary
    summary: Option<TestCaseSummary>,
}

impl SessionActor {
    /// Create a new session actor
    pub fn new(
        session_id: Uuid,
        plugin_actor: Option<ActorRef<PluginActor>>,
        ai_actor: Option<ActorRef<AIOrchestrationActor>>,
        report_actor: Option<ActorRef<ReportActor>>,
    ) -> Self {
        Self {
            session_id,
            variables: HashMap::new(),
            plugin_actor,
            ai_actor,
            report_actor,
            current_test_case: None,
            summary: None,
        }
    }
    
    /// Start session
    async fn start_session(
        &mut self,
        test_case: TestCase,
        parameters: ValueMap,
    ) -> Result<SessionResponse> {
        tracing::info!("Starting session: {}", self.session_id);
        
        self.current_test_case = Some(test_case.clone());
        self.variables.extend(parameters);
        
        // Initialize session summary
        self.summary = Some(TestCaseSummary::new(
            test_case.id,
            test_case.config.name.clone(),
            "/tmp".to_string(), // TODO: Use actual root directory
        ));
        
        Ok(SessionResponse::SessionStarted {
            session_id: self.session_id,
        })
    }
    
    /// Update variables
    async fn update_variables(&mut self, variables: ValueMap) {
        self.variables.extend(variables);
    }
    
    /// Get session summary
    async fn get_session_summary(&self) -> Result<SessionResponse> {
        if let Some(ref summary) = self.summary {
            Ok(SessionResponse::SessionSummary {
                summary: summary.clone(),
            })
        } else {
            Ok(SessionResponse::Error {
                message: "No session summary available".to_string(),
            })
        }
    }
    
    /// Stop session
    async fn stop_session(&mut self) -> Result<SessionResponse> {
        if let Some(mut summary) = self.summary.take() {
            summary.finalize();
            
            Ok(SessionResponse::SessionCompleted {
                session_id: self.session_id,
                summary,
            })
        } else {
            Ok(SessionResponse::Error {
                message: "No active session to stop".to_string(),
            })
        }
    }
}

#[async_trait]
impl Actor for SessionActor {
    async fn started(&mut self, _ctx: &mut ActorContext) {
        tracing::info!("SessionActor started: {}", self.session_id);
    }
}

#[async_trait]
impl Handler<SessionMessage> for SessionActor {
    async fn handle(&mut self, msg: SessionMessage, _ctx: &mut ActorContext) -> SessionResponse {
        match msg {
            SessionMessage::StartSession { test_case, parameters } => {
                match self.start_session(test_case, parameters).await {
                    Ok(response) => response,
                    Err(e) => SessionResponse::Error {
                        message: e.to_string(),
                    },
                }
            }

            SessionMessage::UpdateVariables { variables } => {
                self.update_variables(variables).await;
                SessionResponse::SessionStarted { session_id: self.session_id } // Return something
            }

            SessionMessage::GetSessionSummary => {
                match self.get_session_summary().await {
                    Ok(response) => response,
                    Err(e) => SessionResponse::Error {
                        message: e.to_string(),
                    },
                }
            }

            SessionMessage::StopSession => {
                match self.stop_session().await {
                    Ok(response) => response,
                    Err(e) => SessionResponse::Error {
                        message: e.to_string(),
                    },
                }
            }
        }
    }
}
